package com.zmn.oms.dubbo.impl.zmn.normal.orderpay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.google.common.collect.Lists;
import com.zmn.base.common.data.common.dro.tags.TagsDRO;
import com.zmn.base.common.data.common.query.tags.TagsQuery;
import com.zmn.base.common.data.dubbo.interfaces.tags.TagsListRemoteService;
import com.zmn.base.shortlink.common.dio.shortlink.ShortLinkDIO;
import com.zmn.base.shortlink.common.dro.shortlink.ShortLinkDRO;
import com.zmn.base.shortlink.dubbo.interfaces.shortlink.ShortLinkModifyRemoteService;
import com.zmn.cds.httpcall.CdsHttpCallClient;
import com.zmn.cds.httpcall.CdsHttpCallResult;
import com.zmn.cds.httpcall.biz.orderclue.QueryOrderClueDIO;
import com.zmn.cds.httpcall.biz.orderclue.QueryOrderClueDRO;
import com.zmn.common.constant.FicoConsts;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.math.MathUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.base.invoice.dubbo.interfaces.manage.InvoiceInfoListRemoteService;
import com.zmn.oms.business.interfaces.conf.channel.ConfOrderChannelBService;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageSendBaseService;
import com.zmn.oms.business.interfaces.work.OrderWorkPositionBService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dio.normal.pay.VerifyProgressDIO;
import com.zmn.oms.common.dro.PayChannelDRO;
import com.zmn.oms.common.dro.conf.channel.ConfOrderChannelDRO;
import com.zmn.oms.common.dro.orderpay.OrderPayResultDRO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.dubbo.dto.common.orderpay.*;
import com.zmn.oms.dubbo.dto.common.work.BaseRequestDIO;
import com.zmn.oms.dubbo.impl.OmsBaseRemoteService;
import com.zmn.oms.dubbo.interfaces.zmn.normal.orderpay.OrderPayRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.dto.messageV1.SmsMessageDTO;
import com.zmn.oms.model.dto.work.masterwork.CompleteDTO;
import com.zmn.oms.model.dto.work.modify.must.ZsOrderPayDTO;
import com.zmn.oms.model.dto.work.position.OrderWorkPositionManualSyncDIO;
import com.zmn.oms.model.entity.acceptance.OrderWorkAcceptance;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.visit.OrderVisit;
import com.zmn.oms.model.entity.visit.OrderVisitQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.acceptance.OrderWorkAcceptanceService;
import com.zmn.oms.services.interfaces.orderpay.AccountPayBService;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.visit.OrderVisitService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.dj58.DaoJia58Consts;
import com.zmn.oms.third.dj58.service.DaoJia58Service;
import com.zmn.oms.zmn.business.interfaces.orderpay.OrderPayChannelBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkAmountBService;
import com.zmn.oms.zmn.business.interfaces.work.orderpay.OrderPayResultBService;
import com.zmn.oms.zmn.business.interfaces.work.orderpay.ZsOrderPayBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.masterwork.ZsNormalMasterWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.pay.gateway.common.model.dro.PayGatewayDRO;
import com.zmn.saas.dubbo.interfaces.applique.AppliqueRemoteService;
import com.zmn.track.common.constant.TrackConsts;
import com.zmn.track.common.dio.TrackWorkQueryDIO;
import com.zmn.track.dubbo.dto.TrackWorkQuery;
import com.zmn.track.dubbo.interfaces.trackwork.TrackWorkListRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 类描述：普通工单-金额支付
 *
 * @author heciqi
 * @date 2019/01/10 17:24
 */
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 5000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "true")
public class OrderPayRemoteServiceImpl extends OmsBaseRemoteService implements OrderPayRemoteService {

    @Reference(version = com.zmn.track.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private TrackWorkListRemoteService trackWorkListRemoteService;
    @Reference(version = com.zmn.erp.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private InvoiceInfoListRemoteService invoiceInfoListRemoteService;
    @Reference(version = com.zmn.saas.dubbo.constant.SaasDubboConsts.INTERFACE_VERSION, check = false)
    private AppliqueRemoteService appliqueRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private TagsListRemoteService tagsListRemoteService;
    @Reference(version = com.zmn.base.shortlink.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private ShortLinkModifyRemoteService shortLinkModifyRemoteService;
    @Autowired
    private ZsOrderPayBService zsOrderPayBService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private ZsNormalMasterWorkBService zsNormalMasterWorkBService;
    @Autowired
    private ZsOrderWorkAmountBService zsOrderWorkAmountBService;
    @Autowired
    private OrderProductService orderProductService;
    @Autowired
    private DaoJia58Service daoJia58Service;
    @Autowired
    private OrderWorkPositionBService orderWorkPositionBService;
    @Autowired
    private OrderPayChannelBService orderPayChannelBService;
    @Autowired
    private AccountPayBService accountPayBService;
    @Autowired
    private OrderLogBService orderLogBService;
    @Autowired
    private OrderPayResultBService orderPayResultBService;
    @Autowired
    private MessageSendBaseService messageSendBaseService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private OrderVisitService orderVisitService;
    @Autowired
    private OrderWorkAcceptanceService orderWorkAcceptanceService;

    @Resource
    ConfOrderChannelBService confOrderChannelBService;

    @NacosValue(value = "${enable.ecitic.xiaochengxupay:true}", autoRefreshed = true)
    private boolean enableEciticXiaochengPay;
    @Value("${spring.profiles.active}")
    private String active;
    @Value("${order.agentpay.url:http://test2-h5.xiujiadian.com/wxuser/brand/#/subPackages/shortLink/index?agentType=2&orderId=%s&payAmountType=%s&orderPayId=%s}")
    private String orderAgentPayUrl;

    /**
     * 获取用户支付渠道
     *
     * @param orderId
     * @return
     */
    @Override
    public ResponseDTO<UserPayChannelDRO> getUserPayChannel(Long orderId) {
        log.info("订单用户支付入参：{}", orderId);
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, orderId);
        if (orderWork == null) {
            return ResponseDTO.fail("工单不存在");
        }

        List<PayChannelDRO> listPayChannel = orderPayChannelBService.listPayChannel(orderWork.getPlatWork(), orderWork.getBizModeSource(), orderWork.getChannelId(), orderWork.getServProductGroupId());
        // 是否渠道支付
        boolean channelPay = listPayChannel.stream().anyMatch(e -> Objects.equals(e.getPayChannelId(), PayConsts.PAY_CHANNEL_PLATFORM_CHANNEL));
        if (channelPay) {
            return ResponseDTO.fail(orderWork.getChannelName() + "不支持支付");
        }
        // 是否支持中信支付
        boolean eciticPay = listPayChannel.stream()
                .anyMatch(e -> Objects.equals(e.getPayChannelId(), PayConsts.PAY_CHANNEL_THIRD_ECITIC));
        UserPayChannelDRO userPayChannelDRO;

        if (eciticPay && enableEciticXiaochengPay) {
            log.info("支持中信支付");
            userPayChannelDRO = UserPayChannelDRO.builder()
                    .orderId(orderId)
                    .weixinpayChannleId(PayConsts.PAY_CHANNEL_THIRD_ECITIC)
                    .weixinpayType(PayConsts.PAY_TYPE_SERVNUMBERPAY)
                    .weixinpayTargetChannelId(null)
                    .alipayChannleId(PayConsts.PAY_CHANNEL_THIRD_ECITIC)
                    .alipayType(PayConsts.PAY_TYPE_SERVNUMBERPAY)
                    .alipayTargetChannelId(PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY)
                    .build();
        } else {
            userPayChannelDRO = UserPayChannelDRO.builder()
                    .orderId(orderId)
                    .weixinpayChannleId(PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY)
                    .weixinpayType(PayConsts.PAY_TYPE_SERVNUMBERPAY)
                    .alipayChannleId(PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY)
                    .alipayType(PayConsts.PAY_TYPE_XIAOCHENGXU)
                    .build();
        }
        log.info("订单用户支付出参：{}", userPayChannelDRO);
        return ResponseDTO.success(userPayChannelDRO);
    }

    /**
     * 工单支付信息
     *
     * @param orderId
     * @return
     */
    @Override
    public ResponseDTO<OrderPayInfoDRO> getOrderPayInfo(Long orderId) {
        logger.info("[{}]取工单支付信息", orderId);
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, orderId);
        if (orderWork == null) {
            return ResponseDTO.fail("工单不存在");
        }

        OrderPayInfoDRO orderPayInfoDRO = new OrderPayInfoDRO();
        orderPayInfoDRO.setOrderId(orderWork.getOrderId());
        orderPayInfoDRO.setWorkId(orderWork.getWorkId());
        // 商品名称
        String showProductName = "家电维修";
        List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(orderId);
        if (!CollectionUtils.isEmpty(orderProducts)) {
            showProductName = StringUtils.defaultIfBlank(orderProducts.get(0).getShowProductName(), showProductName);
        }
        orderPayInfoDRO.setShowProductName(showProductName);

        orderPayInfoDRO.setOriginalAmount(orderWork.getOriginalAmount());
        orderPayInfoDRO.setDiscountAmount(orderWork.getDiscountAmount());
        orderPayInfoDRO.setRefundAmount(orderWork.getRefundAmount());
        orderPayInfoDRO.setPayStatus(orderWork.getPayStatus());
        orderPayInfoDRO.setChannelPrepayStatus(orderWork.getChannelPrepayStatus());
        orderPayInfoDRO.setPrepayStatus(orderWork.getPrepayStatus());
        orderPayInfoDRO.setDepositStatus(orderWork.getDepositStatus());
        orderPayInfoDRO.setMasterPayStatus(orderWork.getMasterPayStatus());

        // 渠道预付
        Integer paidChannelPrepayAmount = null;
        if (Objects.equals(orderWork.getChannelPrepayStatus(), PayConsts.PAY_STATUS_DONE)) {
            // 已付
            orderPayInfoDRO.setPaidChannelPrepayAmount(orderWork.getChannelPrepayAmount());
        } else {
            // 未付
            orderPayInfoDRO.setUnPaidChannelPrepayAmount(orderWork.getChannelPrepayAmount());
        }

        // 平台预付
        if (Objects.equals(orderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE)) {
            // 已付
            orderPayInfoDRO.setPaidPrepayAmount(orderWork.getPrepayAmount());
        } else {
            // 未付
            orderPayInfoDRO.setUnPaidPrepayAmount(orderWork.getPrepayAmount());
        }

        // 定金
        if (Objects.equals(orderWork.getDepositStatus(), PayConsts.PAY_STATUS_DONE)) {
            // 已付
            orderPayInfoDRO.setPaidDepositAmount(orderWork.getDepositAmount());
        } else {
            // 未付
            orderPayInfoDRO.setUnPaidDepositAmount(Optional.ofNullable(orderWork.getDepositAmount()).orElse(0));
        }

        // 工程师收款金额
        if (Objects.equals(orderWork.getMasterPayStatus(), PayConsts.PAY_STATUS_DONE)) {
            // 已付
            orderPayInfoDRO.setPaidMasterAmount(orderWork.getMasterAmount());
        } else {
            // 未付
            orderPayInfoDRO.setUnPaidMasterAmount(orderWork.getMasterAmount());
        }

        // 处理未支付进度款
        this.processProgressAmount(orderPayInfoDRO, orderWork);

        // 已付金额（总的）
        Integer paidAmount = Optional.ofNullable(orderPayInfoDRO.getPaidChannelPrepayAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getPaidPrepayAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getPaidDepositAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getPaidMasterAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getPaidProgressAmount()).orElse(0);

        // 待付金额（总的）
        Integer unPaidAmount = Optional.ofNullable(orderPayInfoDRO.getUnPaidChannelPrepayAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getUnPaidPrepayAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getUnPaidDepositAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getUnPaidMasterAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getUnPaidProgressAmount()).orElse(0);

        orderPayInfoDRO.setPaidAmount(paidAmount);
        orderPayInfoDRO.setUnPaidAmount(unPaidAmount);
        List<PayChannelDRO> listPayChannel = orderPayChannelBService.listPayChannel(orderWork.getPlatWork(), orderWork.getBizModeSource(), orderWork.getChannelId(), orderWork.getServProductGroupId());
        boolean eciticPay = listPayChannel.stream()
                .anyMatch(e -> Objects.equals(e.getPayChannelId(), PayConsts.PAY_CHANNEL_THIRD_ECITIC));
        if (eciticPay && enableEciticXiaochengPay) {
            orderPayInfoDRO.setXiaoChengXuPayChannelId(PayConsts.PAY_CHANNEL_THIRD_ECITIC);
        } else {
            orderPayInfoDRO.setXiaoChengXuPayChannelId(PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY);
        }
        logger.info("[{}]工单支付信息[{}]", orderId, orderPayInfoDRO);
        return ResponseDTO.success(orderPayInfoDRO);
    }

    /**
     * 工单支付信息
     *
     * @param orderPayInfoDIO
     * @return
     */
    @Override
    public ResponseDTO<OrderPayInfoDRO> getOrderPayInfo(OrderPayInfoDIO orderPayInfoDIO) {
        logger.info("[{}]取工单支付信息[{}]", orderPayInfoDIO.getOrderId(), JSON.toJSONString(orderPayInfoDIO));
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderPayInfoDIO.getOrderId(), orderPayInfoDIO.getOrderId());

        if (orderWork == null) {
            return ResponseDTO.fail("工单不存在");
        }

        OrderPayInfoDRO orderPayInfoDRO = new OrderPayInfoDRO();
        orderPayInfoDRO.setOrderId(orderWork.getOrderId());
        orderPayInfoDRO.setWorkId(orderWork.getWorkId());
        // 商品名称
        String showProductName = "家电维修";
        List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(orderPayInfoDIO.getOrderId());
        if (!CollectionUtils.isEmpty(orderProducts)) {
            showProductName = StringUtils.defaultIfBlank(orderProducts.get(0).getShowProductName(), showProductName);
        }
        orderPayInfoDRO.setShowProductName(showProductName);

        orderPayInfoDRO.setOriginalAmount(orderWork.getOriginalAmount());
        orderPayInfoDRO.setDiscountAmount(orderWork.getDiscountAmount());
        orderPayInfoDRO.setRefundAmount(orderWork.getRefundAmount());
        orderPayInfoDRO.setPayStatus(orderWork.getPayStatus());
        orderPayInfoDRO.setChannelPrepayStatus(orderWork.getChannelPrepayStatus());
        orderPayInfoDRO.setPrepayStatus(orderWork.getPrepayStatus());
        orderPayInfoDRO.setDepositStatus(orderWork.getDepositStatus());
        orderPayInfoDRO.setMasterPayStatus(orderWork.getMasterPayStatus());

        // 渠道预付
        Integer paidChannelPrepayAmount = null;
        if (Objects.equals(orderWork.getChannelPrepayStatus(), PayConsts.PAY_STATUS_DONE)) {
            // 已付
            orderPayInfoDRO.setPaidChannelPrepayAmount(orderWork.getChannelPrepayAmount());
        } else {
            // 未付
            orderPayInfoDRO.setUnPaidChannelPrepayAmount(orderWork.getChannelPrepayAmount());
        }

        // 平台预付
        if (Objects.equals(orderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE)) {
            // 已付
            orderPayInfoDRO.setPaidPrepayAmount(orderWork.getPrepayAmount());
        } else {
            // 未付
            orderPayInfoDRO.setUnPaidPrepayAmount(orderWork.getPrepayAmount());
        }

        // 定金
        if (Objects.equals(orderWork.getDepositStatus(), PayConsts.PAY_STATUS_DONE)) {
            // 已付
            orderPayInfoDRO.setPaidDepositAmount(orderWork.getDepositAmount());
        } else {
            // 未付
            orderPayInfoDRO.setUnPaidDepositAmount(Optional.ofNullable(orderWork.getDepositAmount()).orElse(0));
        }

        // 工程师收款金额
        if (Objects.equals(orderWork.getMasterPayStatus(), PayConsts.PAY_STATUS_DONE)) {
            // 已付
            orderPayInfoDRO.setPaidMasterAmount(orderWork.getMasterAmount());
        } else {
            // 未付
            orderPayInfoDRO.setUnPaidMasterAmount(orderWork.getMasterAmount());
        }

        // 处理未支付进度款
        //this.processProgressAmount(orderPayInfoDRO, orderWork);

        // 已付金额（总的）
        Integer paidAmount = Optional.ofNullable(orderPayInfoDRO.getPaidChannelPrepayAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getPaidPrepayAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getPaidDepositAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getPaidMasterAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getPaidProgressAmount()).orElse(0);

        // 待付金额（总的）
        Integer unPaidAmount = Optional.ofNullable(orderPayInfoDRO.getUnPaidChannelPrepayAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getUnPaidPrepayAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getUnPaidDepositAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getUnPaidMasterAmount()).orElse(0)
                + Optional.ofNullable(orderPayInfoDRO.getUnPaidProgressAmount()).orElse(0);

        orderPayInfoDRO.setPaidAmount(paidAmount);
        orderPayInfoDRO.setUnPaidAmount(unPaidAmount);
        List<PayChannelDRO> listPayChannel = orderPayChannelBService.listPayChannel(orderWork.getPlatWork(), orderWork.getBizModeSource(), orderWork.getChannelId(), orderWork.getServProductGroupId());
        boolean eciticPay = listPayChannel.stream()
                .anyMatch(e -> Objects.equals(e.getPayChannelId(), PayConsts.PAY_CHANNEL_THIRD_ECITIC));
        if (eciticPay && enableEciticXiaochengPay) {
            orderPayInfoDRO.setXiaoChengXuPayChannelId(PayConsts.PAY_CHANNEL_THIRD_ECITIC);
        } else {
            orderPayInfoDRO.setXiaoChengXuPayChannelId(PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY);
        }
        try {
            this.processAcceptance(orderPayInfoDRO, orderPayInfoDIO);
        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getMessage());
        }
        logger.info("[{}]工单支付信息[{}]", orderPayInfoDIO.getOrderId(), orderPayInfoDRO);
        return ResponseDTO.success(orderPayInfoDRO);
    }

    private void processAcceptance(OrderPayInfoDRO orderPayInfoDRO, OrderPayInfoDIO orderPayInfoDIO) throws OmsBaseException {

        // 如果支付明细id不是空，优先取支付明细表数据
        if (NumberUtil.isNotNullOrZero(orderPayInfoDIO.getOrderPayId())) {
            OrderPay orderPay = orderPayService.findOrderPayByKeySrcMaster(orderPayInfoDRO.getOrderId(), orderPayInfoDIO.getOrderPayId());
            if (Objects.isNull(orderPay)) {
                throw new OmsBaseException("当前支付已取消");
            }
            if (Objects.equals(orderPay.getAmountType(), OrderPayConsts.ORDER_PAY_DEPOSIT)) {
                orderPayInfoDRO.setDepositStatus(orderPay.getPayStatus());
                if (Objects.equals(orderPay.getPayStatus(), PayConsts.PAY_STATUS_NONE)) {
                    orderPayInfoDRO.setUnPaidDepositAmount(orderPay.getAmount());
                    orderPayInfoDRO.setUnPaidMasterAmount(Optional.ofNullable(orderPayInfoDRO.getUnPaidMasterAmount()).orElse(0) - orderPay.getAmount());
                } else {
                    orderPayInfoDRO.setPaidDepositAmount(orderPay.getAmount());
                }
            } else if (Objects.equals(orderPay.getAmountType(), OrderPayConsts.ORDER_PAY_PROGRESS)) {
                orderPayInfoDRO.setProgressStatus(orderPay.getPayStatus());
                if (Objects.equals(orderPay.getPayStatus(), PayConsts.PAY_STATUS_NONE)) {
                    orderPayInfoDRO.setUnPaidProgressAmount(orderPay.getAmount());
                    orderPayInfoDRO.setUnPaidMasterAmount(Optional.ofNullable(orderPayInfoDRO.getUnPaidMasterAmount()).orElse(0) - orderPay.getAmount());
                } else {
                    orderPayInfoDRO.setPaidProgressAmount(orderPay.getAmount());
                }
            }
            return;
        }

        OrderWorkAcceptance orderWorkAcceptance = orderWorkAcceptanceService.findOrderWorkAcceptanceByKeySrcMaster(orderPayInfoDIO.getAcceptanceId(), orderPayInfoDRO.getOrderId());
        // 如果验收不存在或者不是多次上门验收返回
        if (Objects.isNull(orderWorkAcceptance) || NumberUtil.isNullOrZero(orderWorkAcceptance.getVisitId())) {
            return;
        }

        OrderVisitQuery query = new OrderVisitQuery();
        query.setOrderId(orderPayInfoDRO.getOrderId());
        query.setVisitId(orderWorkAcceptance.getVisitId());
        OrderVisit orderVisit = orderVisitService.findOrderVisitByQuerySrcMaster(query);
        // 如果多次上门不存在返回
        if (Objects.isNull(orderVisit)) {
            return;
        }

        if (Objects.equals(orderWorkAcceptance.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT)) {
            orderPayInfoDRO.setDepositStatus(orderVisit.getPayStatus());
            if (Objects.equals(orderVisit.getPayStatus(), PayConsts.PAY_STATUS_NONE)) {
                orderPayInfoDRO.setUnPaidDepositAmount(orderVisit.getAmount());
                orderPayInfoDRO.setUnPaidMasterAmount(Optional.ofNullable(orderPayInfoDRO.getUnPaidMasterAmount()).orElse(0) - orderVisit.getAmount());
            } else {
                orderPayInfoDRO.setPaidDepositAmount(orderVisit.getAmount());
            }
        } else if (Objects.equals(orderWorkAcceptance.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PROGRESS)) {
            orderPayInfoDRO.setProgressStatus(orderVisit.getPayStatus());
            if (Objects.equals(orderVisit.getPayStatus(), PayConsts.PAY_STATUS_NONE)) {
                orderPayInfoDRO.setUnPaidProgressAmount(orderVisit.getAmount());
                orderPayInfoDRO.setUnPaidMasterAmount(Optional.ofNullable(orderPayInfoDRO.getUnPaidMasterAmount()).orElse(0) - orderVisit.getAmount());
            } else {
                orderPayInfoDRO.setPaidProgressAmount(orderVisit.getAmount());
            }
        }
    }

    /**
     * 处理进度款
     *
     * @param orderPayInfoDRO
     * @param orderWork
     */
    private void processProgressAmount(OrderPayInfoDRO orderPayInfoDRO, OrderWork orderWork) {

        // 查询支付信息
        List<OrderPay> orderPayList = orderPayService.listOrderPayByOrderId(orderWork.getOrderId());
        if (CollectionUtil.isNullOrEmpty(orderPayList)) {
            return;
        }

        int depositAmount = 0; // 已付定金
        int unDepositAmount = 0; // 未付定金
        int progressAmount = 0; // 已付进度款
        int unProgressAmount = 0; // 未付进度款

        for (OrderPay orderPay : orderPayList) {

            // 定金
            if (Objects.equals(OrderPayConsts.ORDER_PAY_DEPOSIT, orderPay.getAmountType())) {
                if (Objects.equals(orderPay.getPayStatus(), PayConsts.PAY_STATUS_NONE)) {
                    unDepositAmount += orderPay.getAmount();
                    orderPayInfoDRO.setDepositStatus(PayConsts.PAY_STATUS_NONE);
                } else {
                    depositAmount += orderPay.getAmount();
                }
            }
            // 进度款
            else {
                if (Objects.equals(orderPay.getPayStatus(), PayConsts.PAY_STATUS_NONE)) {
                    unProgressAmount += orderPay.getAmount();
                    orderPayInfoDRO.setProgressStatus(PayConsts.PAY_STATUS_NONE);
                } else {
                    progressAmount += orderPay.getAmount();
                }
            }
        }
        orderPayInfoDRO.setPaidDepositAmount(depositAmount == 0 ? null : depositAmount);
        orderPayInfoDRO.setUnPaidDepositAmount(unDepositAmount == 0 ? null : unDepositAmount);
        orderPayInfoDRO.setPaidProgressAmount(progressAmount == 0 ? null : progressAmount);
        orderPayInfoDRO.setUnPaidProgressAmount(unProgressAmount == 0 ? null : unProgressAmount);
    }

    /**
     * 获取支付状态
     * l
     *
     * @param baseRequestDIO
     * @return
     */
    @Override
    public ResponseDTO<OrderLocalPayDRO> checkLocalPay(BaseRequestDIO baseRequestDIO) {

        OrderLocalPayDRO orderLocalPayDRO = new OrderLocalPayDRO();

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(baseRequestDIO.getOrderId(), baseRequestDIO.getWorkId());

        // 工程师收款为0或支付状态为已支付，不校验
        if (Objects.equals(0, orderWork.getMasterAmount()) || Objects.equals(orderWork.getPayStatus(), PayConsts.PAY_STATUS_DONE)) {
            return ResponseDTO.success(orderLocalPayDRO);
        }

        // 1、返修单 不校验现场支付
        if (Objects.equals(OrderConsts.ORDER_TYPE_REWORK, orderWork.getType())) {
            return ResponseDTO.success(orderLocalPayDRO);
        }
        // 2、特殊渠道不校验 特殊渠道ID：32794、33551、1210、10108、1522、33727、33930、33979、32809
        if (ChannelConsts.CHANNEL_ID_NON_CHECK_LOCAL_PAY.contains(orderWork.getChannelId())
                || ChannelConsts.CHANNEL_OPENAPI_SUPPORT_PAYLINK.containsKey(orderWork.getChannelId())) {
            return ResponseDTO.success(orderLocalPayDRO);
        }
        // 3、订单是否满足 服务分类：家电安装 后台一级：空调
        if (Objects.equals(GlobalConsts.SERV_CATEG_INSTALL, orderWork.getServCategId())
                && Objects.equals(ProductConsts.CATEG_ONE_ID_AC, orderWork.getCategOneId())) {
            return ResponseDTO.success(orderLocalPayDRO);
        }
        // 4、后台是否提交了验券（无论成功/ 失败） 判断操作日志
        List<OrderLog> orderLogList = orderLogBService.findOrderLogsByTypes(baseRequestDIO.getWorkId(), Lists.newArrayList(OrderLogConsts.ORDER_LOG_TYPE_USE_COUPON, OrderLogConsts.ORDER_LOG_TYPE_DISCOUNT_ARTIFICIAL_OPERATOR));
        if (CollectionUtils.isNotEmpty(orderLogList)) {
            return ResponseDTO.success(orderLocalPayDRO);
        }

        // 4、此工程师是否发起了对公转账跟单（跟单ID：1115）, 忽略跟单状态
        TrackWorkQueryDIO queryDIO = new TrackWorkQueryDIO();
        queryDIO.setOrderId(orderWork.getOrderId());
        queryDIO.setWorkId(orderWork.getWorkId());
        queryDIO.setTrackContentIdList(Lists.newArrayList(TrackConsts.TRACK_CONTENT_ID_CORPORATE_ACCOUNT));
        ResponseDTO<Integer> responseDTO = trackWorkListRemoteService.countTrackWorkByQuery(queryDIO);
        if (responseDTO.isSuccess() && responseDTO.getData() > 0) {
            return ResponseDTO.success(orderLocalPayDRO);
        }

        // 5、用户是否成功发起开票申请
//		ResponseDTO<Boolean> booleanResponseDTO = invoiceInfoListRemoteService.isAppliedInvoice(orderWork.getWorkId());
//		if (booleanResponseDTO.isSuccess() && booleanResponseDTO.getData() == true) {
//			return ResponseDTO.success(orderLocalPayDRO);
//		}

        try {
            ConfOrderChannelDRO confOrderChannelDRO = confOrderChannelBService.getByChannelId(orderWork.getChannelId());
            if (Objects.nonNull(confOrderChannelDRO) && Objects.equals(confOrderChannelDRO.getGuideThirdPartPay(), GlobalConsts.YES)) {
                orderLocalPayDRO.setNeedPayImmediately(confOrderChannelDRO.getShowPayQr());
            }
            zsOrderPayBService.checkChannelOrderConfig(baseRequestDIO.getVersion(), orderWork);
            List<PayChannelDRO> listPayChannel = orderPayChannelBService.listThirdPayChannel(orderWork.getChannelId());
            if (CollectionUtil.isNotNullOrEmpty(listPayChannel)) {
                com.zmn.pay.gateway.common.model.dro.PayGatewayDRO channelPayQrCode = zsOrderPayBService.getChannelPayQrCode(orderWork, listPayChannel.get(0).getPayChannelId());
                if (Objects.nonNull(channelPayQrCode)) {
                    orderLocalPayDRO.setCode(AppConsts.APP_PAY_FLAG_THIRD_PAY);
                }
            }
        } catch (OmsBaseException omsException) {
            if (omsException.getCode().equals(AppConsts.APP_PAY_FLAG_CHANNEL_PRICE) ||
                    omsException.getCode().equals(AppConsts.APP_PAY_FLAG_CHANNEL_GUIDE) ||
                    omsException.getCode().equals(AppConsts.APP_PAY_FLAG_CHANNEL_GUIDE_NO_EXPLAIN)) {
                orderLocalPayDRO.setCode(omsException.getCode());
                orderLocalPayDRO.setMsg(omsException.getMessage());
                return ResponseDTO.success(orderLocalPayDRO);
            }
            return ResponseDTO.fail(omsException.getMessage());
        }

        // 检查支付距离 距离判断  现场支付定义：根据点击【服务完成】时的位置与用户家的位置比对，小于XXX米，则认为现场
        if (Objects.isNull(baseRequestDIO.getLongitude()) || Objects.isNull(baseRequestDIO.getLatitude()) || baseRequestDIO.getLatitude() == 0D) {
            // 若未获取当前位置则视为在现场支付
            return ResponseDTO.success(orderLocalPayDRO);
        }

        Integer distance = orderWorkPositionBService.customerMinPayDistance(orderWork.getWorkId(), orderWork.getVisitUserId(), baseRequestDIO.getLongitude(), baseRequestDIO.getLatitude());
        // 查询最大支付距离
        TagsQuery baseCodeMapDIO = new TagsQuery();
        baseCodeMapDIO.setOneTypeId(OrderConsts.BASE_CODE_MAP_ONE_TYPE_LOCAL_PAY);
        baseCodeMapDIO.setStatus(GlobalConsts.YES);
        baseCodeMapDIO.setPlat(orderWork.getPlatWork());
        ResponseDTO<List<TagsDRO>> listResponseDTO = tagsListRemoteService.listByTagsDIO(baseCodeMapDIO);
        if (CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return ResponseDTO.success(orderLocalPayDRO);
        }

        //  最大距离 超出提示发起支付异常跟单
        int minDistance = listResponseDTO.getData().get(0).getThreeTypeId();
        if (distance <= minDistance) {
            return ResponseDTO.success(orderLocalPayDRO);
        }

        // 查询是否有未完成异常跟单
        TrackWorkQuery trackWorkQueryDIO = new TrackWorkQuery();
        trackWorkQueryDIO.setOrderId(orderWork.getOrderId());
        trackWorkQueryDIO.setWorkId(orderWork.getWorkId());
        trackWorkQueryDIO.setTrackContentIdList(Lists.newArrayList(TrackConsts.TRACK_CONTENT_ID_NO_SCENE_PAY));
        trackWorkQueryDIO.setStatus(TrackConsts.TRACK_STATUS_FINISHED);
        ResponseDTO<Integer> countResponseDTO = trackWorkListRemoteService.countTrackByQuery(trackWorkQueryDIO);
        if (countResponseDTO.isSuccess() && Objects.equals(GlobalConsts.NONE, countResponseDTO.getData())) {
            orderLocalPayDRO.setCode(AppConsts.APP_PAY_FLAG_POSITION);
            orderLocalPayDRO.setMsg(String.format("超出用户家%skm无法支付，请发起跟单并联系主管。", MathUtil.div(distance, 1000, 2)));
        }

        return ResponseDTO.success(orderLocalPayDRO);
    }

    /**
     * 获取支付状态
     * l
     *
     * @param baseRequestDIO
     * @return 0 不需要支付，1 需要支付，2 已支付，3 提示用户支付
     */
    @Override
    public ResponseDTO<Integer> getPayStatus(BaseRequestDIO baseRequestDIO) {
        ResponseDTO<Integer> responseDTO;

        try {
            // 完成前检测
            CompleteDTO completeDTO = BeanMapper.map(baseRequestDIO, CompleteDTO.class);
            zsNormalMasterWorkBService.checkComplete(completeDTO);

            OrderWork orderWork = orderWorkService.findOrderWorkByKey(baseRequestDIO.getOrderId(), baseRequestDIO.getWorkId());
            int payFlag;
            // F单，自动支付
            if (Objects.equals(OrderConsts.ORDER_TYPE_NEW, orderWork.getType())
                    && Objects.equals(com.zmn.consts.GlobalConsts.BIZ_TYPE_F, orderWork.getBizType())
                    && !ChannelConsts.CHANNEL_ID_NOSUPPORT_ACCOUNT_PAY.contains(orderWork.getChannelId())
                    && !Objects.equals(PayConsts.PAY_STATUS_DONE, orderWork.getPayStatus())
            ) {
                ZsOrderPayDTO zsOrderPayDTO = new ZsOrderPayDTO();
                zsOrderPayDTO.setPayChannelId(accountPayBService.getPayChannelIdByOrderId(orderWork.getOrderId()));
                zsOrderPayDTO.setPayType(PayConsts.PAY_TYPE_INTO);
                zsOrderPayDTO.setTransferTime(new Date());
                zsOrderPayDTO.setSyncFlag(com.zmn.consts.GlobalConsts.YES);
                zsOrderPayDTO.setOrderId(orderWork.getOrderId());
                zsOrderPayDTO.setWorkId(orderWork.getWorkId());
                zsOrderPayDTO.setPlat(orderWork.getPlatWork());
                zsOrderPayDTO.setOperatorPlat(orderWork.getPlatWork());
                zsOrderPayDTO.setOperator(com.zmn.common.constant.GlobalConsts.getOperatorTypeName(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                zsOrderPayDTO.setOperatorId(Long.valueOf(com.zmn.consts.GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                zsOrderPayDTO.setOperatorType(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
                zsOrderPayDTO.setAccountType(FicoConsts.ACC_FACTORY);
                // 同步支付
                PayGatewayDRO payGatewayDRO = zsOrderPayBService.payMasterAmount(zsOrderPayDTO);
                // 更新支付结果
                OrderPayResultDRO orderPayResultDRO = orderPayResultBService.convertOrderPayResult(payGatewayDRO.getStatus());
                orderPayResultDRO.setAmountType(OrderPayConsts.ORDER_PAY_MASTER);
                zsOrderWorkAmountBService.updateMasterAmountPayResult(orderPayResultDRO);
                // 更新完成
                zsNormalMasterWorkBService.completeOrder(completeDTO);
                payFlag = AppConsts.ORDER_PAY_FLAG_PAID;
            } else {
                payFlag = zsOrderPayBService.getPayFlag(orderWork);
            }

            // 手动同步工单位置以备某些支付方式没有经纬度
            if (Objects.equals(AppConsts.APP_PAY_FLAG_ALERT_USER_PAY, payFlag) || Objects.equals(AppConsts.APP_PAY_FLAG_VISIT_USER, payFlag) ||
                    Objects.equals(AppConsts.APP_PAY_FLAG_VISIT_USER_FALSE, payFlag) || Objects.equals(AppConsts.ORDER_PAY_FLAG_UNPAID, payFlag)) {
                OrderWorkPositionManualSyncDIO dio = new OrderWorkPositionManualSyncDIO(baseRequestDIO.getLongitude(), baseRequestDIO.getLatitude(), Lists.newArrayList(OrderLogConsts.ORDER_LOG_TYPE_PAY, OrderLogConsts.ORDER_LOG_TYPE_COMPLETE), baseRequestDIO.getMasterName());
                orderWorkPositionBService.manualSyncOrderPayPosition(orderWork, dio);
            }

            if (Objects.equals(payFlag, AppConsts.APP_PAY_FLAG_ALERT_USER_PAY)) {// 特殊渠道提示用户支付
                responseDTO = ResponseDTO.success(payFlag);
                return responseDTO;
            }

            // 未支付的订单，特定条件的（58到家同城公寓渠道和大客户订单）需要特殊处理
            if (Objects.equals(AppConsts.ORDER_PAY_FLAG_UNPAID, payFlag)) {
                // 58到家-同城公寓  2020-05-20 by lhl
                // 啄木鸟调“发起补充支付“接口同步补尾款金额至58（注：58返回成功即为默认支付成功，工程师收款额即为渠道代收金额）
                // 啄木鸟发起完成：啄木鸟调“同步订单完成“接口同步完成至58（以调取支付链接返回成功为节点工单状态置为已完成）
                if (Objects.equals(DaoJia58Consts.CHANNEL_ID_APARTMENT, orderWork.getChannelId())) {
                    // TODO -lhl 58到家-同城公寓
                    daoJia58Service.secondPay4apartmentOrder(orderWork.getOrderId());
                    payFlag = AppConsts.ORDER_PAY_FLAG_PAID;
                }
            }

            responseDTO = ResponseDTO.success(payFlag);
        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }

        return responseDTO;
    }

    /**
     * 获取支付渠道和支付方式
     *
     * @param baseRequestDIO
     * @return
     */
    @Override
    public ResponseDTO<List<PayChannelDRO>> listPayChannel(BaseRequestDIO baseRequestDIO) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(baseRequestDIO.getOrderId(), baseRequestDIO.getWorkId());
        List<PayChannelDRO> payChannelDROS = orderPayChannelBService.listPayChannel(orderWork.getPlatWork(), orderWork.getBizModeSource(), orderWork.getChannelId(), orderWork.getServProductGroupId());

        // 需要渠道支付二维码
        boolean needChannelPayQrCode = Optional.ofNullable(payChannelDROS)
                // 需要在第三方平台支付
                .map(payChannelDROLis -> payChannelDROLis.size() == 1 ? payChannelDROLis.get(0) : null)
                .map(payChannelDRO ->
                        Objects.equals(PayConsts.PAY_CHANNEL_PLATFORM_CHANNEL, payChannelDRO.getPayChannelId())
                                ? payChannelDRO.getPayTypeList()
                                : null
                )
                // 支付方式为：二维码支付
                .map(payTypeList -> payTypeList.size() == 1 ? payTypeList.get(0) : null)
                .map(payType -> Objects.equals(PayConsts.PAY_TYPE_QR, payType) ? payType : null)
                .isPresent();

//        if (Objects.equals(orderWork.getChannelId(), ChannelConsts.CHANNEL_ID_WANKE) && needChannelPayQrCode) {
//            // 如果是万科的渠道订单查询该订单是否已经在万科那边服务完成，如果服务已经完成就不需要获取第三方支付链接
//            // 创建 CdsHttpCallClient 对象
//            CdsHttpCallClient client = CdsHttpCallClient.newInstance(
//                    CdsConsts.HttpCall.BASE_URL,
//                    CdsConsts.HttpCall.MODEL_NAME,
//                    CdsConsts.HttpCall.SECRET_KEY
//            );
//
//            // 封装请求参数
//            QueryOrderClueDIO dio = new QueryOrderClueDIO();
//            dio.setZmnOrderId(baseRequestDIO.getOrderId());
//            // 获取渠道订单线索
//            CdsHttpCallResult<QueryOrderClueDRO> result = client.queryOrderClue(dio);
//            String extendDataStr = Optional.ofNullable(result.getData())
//                    .map(QueryOrderClueDRO::getOrderClueExtendData)
//                    .orElse(null);
//            if (StringUtil.isNotBlank(extendDataStr)) {
//                HashMap<String, String> extendDataMap = JSON.parseObject(
//                        extendDataStr,
//                        new TypeReference<HashMap<String, String>>() {
//                        }
//                );
//                String merchantConfirm = extendDataMap.get("merchantConfirm");
//                String userConfirm = extendDataMap.get("userConfirm");
//                if (StringUtils.equals(merchantConfirm, "2") && StringUtils.equals(userConfirm,"0")) {
//
//                    // 服务已完成但是用户未确认
////                    needChannelPayQrCode = false;
//                    log.error("【万科幸福社】订单【{}】已经在万科侧服务完成，不能修改价格",baseRequestDIO.getOrderId());
//                    return ResponseDTO.fail("该订单已经在万科侧服务完成，不能修改价格");
//                }
//            }
//        }

        // 预生成渠道支付二维码
        if (needChannelPayQrCode) {
            try {
                zsOrderPayBService.getChannelPayQrCode(orderWork, PayConsts.PAY_CHANNEL_PLATFORM_CHANNEL);
            } catch (OmsBaseException obe) {
                return ResponseDTO.fail(obe.getMessage());
            } catch (Exception e) {
                log.error(String.format("OrderId=[%s]: 获取渠道支付二维码失败：%s", orderWork.getWorkId(), e.getMessage()), e);
                // 其他异常不做处理
            }
        }

        return ResponseDTO.success(payChannelDROS);
    }

    /**
     * 是否仅支持银行转账
     *
     * @param baseRequestDIO
     * @return
     */
    @Override
    public ResponseDTO<Boolean> onlySupportBankTransfer(BaseRequestDIO baseRequestDIO) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(baseRequestDIO.getOrderId(), baseRequestDIO.getWorkId());
        boolean supportBankTransfer = orderPayChannelBService.onlySupportBankTransfer(orderWork.getBizModeSource(), orderWork.getChannelId());
        return ResponseDTO.success(supportBankTransfer);
    }

    /**
     * 预付款支付
     *
     * @param orderPayDIO
     * @return
     */
    @Override
    public ResponseDTO<OrderPayDRO> payPrepaidAmount(OrderPayDIO orderPayDIO) {
        ZsOrderPayDTO zsOrderPayDTO = BeanMapper.map(orderPayDIO, ZsOrderPayDTO.class);
        // 操作人设置
        zsOrderPayDTO.setOperatorType(orderPayDIO.getOperatorType());
        zsOrderPayDTO.setOperatorId(Optional.ofNullable(Long.valueOf(orderPayDIO.getOperatorId())).orElse(0L));
        zsOrderPayDTO.setOperator(orderPayDIO.getOperator());
        try {
            com.zmn.pay.gateway.common.model.dro.PayGatewayDRO payRepsDRO = zsOrderPayBService.payPrepaidAmount(zsOrderPayDTO);
            // DRO转换
            OrderPayDRO orderPayDRO = BeanMapper.map(payRepsDRO, OrderPayDRO.class);
            orderPayDRO.setTradeNo(payRepsDRO.getOutTradeNo());
            // 微信小程序或公众号支付，返回微信jspay模型
            if (payRepsDRO.getWexinJspayDRO() != null) {
                WexinJspayDRO weixinDRO = BeanMapper.map(payRepsDRO.getWexinJspayDRO(), WexinJspayDRO.class);
                orderPayDRO.setWexinJspayDRO(weixinDRO);
            }
            return ResponseDTO.success(orderPayDRO);
        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    /**
     * 定金支付
     *
     * @param orderPayDIO
     * @return
     */
    @Override
    public ResponseDTO<OrderPayDRO> payDepositAmount(OrderPayDIO orderPayDIO) {
        ZsOrderPayDTO zsOrderPayDTO = BeanMapper.map(orderPayDIO, ZsOrderPayDTO.class);
        // 操作人设置
        zsOrderPayDTO.setOperatorType(NumberUtil.isNotNullOrZero(orderPayDIO.getOperatorType()) ? orderPayDIO.getOperatorType() : GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        zsOrderPayDTO.setOperatorId(NumberUtil.isNotNullOrZero(orderPayDIO.getOperatorId()) ? orderPayDIO.getOperatorId() : GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        zsOrderPayDTO.setOperator(StringUtil.isNotBlank(orderPayDIO.getOperator()) ? orderPayDIO.getOperator() : "系统");
        if (Objects.equals(orderPayDIO.getChannelId(), PayConsts.PAY_CHANNEL_PLATFORM_CHANNEL)) {
            return ResponseDTO.fail("渠道不支持定金支付");
        }

        try {
            com.zmn.pay.gateway.common.model.dro.PayGatewayDRO payRepsDRO = zsOrderPayBService.payDepositAmount(zsOrderPayDTO);
            // DRO转换
            OrderPayDRO orderPayDRO = BeanMapper.map(payRepsDRO, OrderPayDRO.class);
            orderPayDRO.setTradeNo(payRepsDRO.getOutTradeNo());
            return ResponseDTO.success(orderPayDRO);
        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    /**
     * 定金支付
     *
     * @param orderPayDIO
     * @return
     */
    @Override
    public ResponseDTO<OrderPayDRO> multipleVisitPayDepositAmount(OrderPayDIO orderPayDIO) {
        logger.info("[{}]多次上门定金支付入参：【{}】", orderPayDIO.getOrderId(), JSON.toJSONString(orderPayDIO));
		/*if (NumberUtil.isNullOrZero(orderPayDIO.getOrderPayId())) {
			return ResponseDTO.fail("支付不存在");
		}*/
        ZsOrderPayDTO zsOrderPayDTO = BeanMapper.map(orderPayDIO, ZsOrderPayDTO.class);
        // 操作人设置
        zsOrderPayDTO.setOperatorType(NumberUtil.isNotNullOrZero(orderPayDIO.getOperatorType()) ? orderPayDIO.getOperatorType() : GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        zsOrderPayDTO.setOperatorId(NumberUtil.isNotNullOrZero(orderPayDIO.getOperatorId()) ? orderPayDIO.getOperatorId() : GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        zsOrderPayDTO.setOperator(StringUtil.isNotBlank(orderPayDIO.getOperator()) ? orderPayDIO.getOperator() : "系统");
        if (Objects.equals(orderPayDIO.getChannelId(), PayConsts.PAY_CHANNEL_PLATFORM_CHANNEL)) {
            return ResponseDTO.fail("渠道不支持定金支付");
        }

        try {
            com.zmn.pay.gateway.common.model.dro.PayGatewayDRO payRepsDRO = zsOrderPayBService.multipleVisitPayDepositAmount(zsOrderPayDTO);
            // DRO转换
            OrderPayDRO orderPayDRO = BeanMapper.map(payRepsDRO, OrderPayDRO.class);
            orderPayDRO.setTradeNo(payRepsDRO.getOutTradeNo());
            return ResponseDTO.success(orderPayDRO);
        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    /**
     * 进度款支付
     *
     * @param orderPayDIO
     * @return
     */
    @Override
    public ResponseDTO<OrderPayDRO> progressPayAmount(OrderPayDIO orderPayDIO) {
        if (NumberUtil.isNullOrZero(orderPayDIO.getOrderPayId())) {
            return ResponseDTO.fail("支付不存在");
        }
        ZsOrderPayDTO zsOrderPayDTO = BeanMapper.map(orderPayDIO, ZsOrderPayDTO.class);
        // 操作人设置
        zsOrderPayDTO.setOperatorType(NumberUtil.isNotNullOrZero(orderPayDIO.getOperatorType()) ? orderPayDIO.getOperatorType() : GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        zsOrderPayDTO.setOperatorId(NumberUtil.isNotNullOrZero(orderPayDIO.getOperatorId()) ? orderPayDIO.getOperatorId() : GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        zsOrderPayDTO.setOperator(StringUtil.isNotBlank(orderPayDIO.getOperator()) ? orderPayDIO.getOperator() : "系统");

        try {
            com.zmn.pay.gateway.common.model.dro.PayGatewayDRO payRepsDRO = zsOrderPayBService.progressPayAmount(zsOrderPayDTO);
            // DRO转换
            OrderPayDRO orderPayDRO = BeanMapper.map(payRepsDRO, OrderPayDRO.class);
            orderPayDRO.setTradeNo(payRepsDRO.getOutTradeNo());
            return ResponseDTO.success(orderPayDRO);
        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    /**
     * 工程师收款支付
     *
     * @param orderPayDIO
     * @return
     */
    @Override
    public ResponseDTO<OrderPayDRO> payMasterAmount(OrderPayDIO orderPayDIO) {
        log.info("OrderPayRemoteServiceImpl#payMasterAmount工程师收款支付请求=====>{}", JSON.toJSONString(orderPayDIO));
        ZsOrderPayDTO zsOrderPayDTO = BeanMapper.map(orderPayDIO, ZsOrderPayDTO.class);
        // 操作人设置
        zsOrderPayDTO.setOperatorType(Optional.ofNullable(orderPayDIO.getOperatorType()).orElse(GlobalConsts.OPERATE_USER_TYPE_MASTER));
        zsOrderPayDTO.setOperatorId(Optional.ofNullable(orderPayDIO.getOperatorId()).orElse(Long.valueOf(Optional.ofNullable(orderPayDIO.getMasterId()).orElse(0))));
        zsOrderPayDTO.setOperator(Optional.ofNullable(orderPayDIO.getOperator()).orElse(orderPayDIO.getMasterName()));

        try {
            PayGatewayDRO payRepsDRO = zsOrderPayBService.payMasterAmount(zsOrderPayDTO);
            // DRO转换
            OrderPayDRO orderPayDRO = BeanMapper.map(payRepsDRO, OrderPayDRO.class);
            orderPayDRO.setTradeNo(payRepsDRO.getOutTradeNo());
            // 修正QrCode是二维码图片地址的情况 2020.12.22 by lhl
            if (StringUtils.isNotBlank(orderPayDRO.getQrCode())) {
                Pattern pattern = Pattern.compile("^(.*?)[&|\\?]isQrCodeImg=true$");
                Matcher matcher = pattern.matcher(orderPayDRO.getQrCode());
                if (matcher.find()) {
                    orderPayDRO.setQrCode(matcher.group(1));
                    orderPayDRO.setQrCodeImg(GlobalConsts.YES);
                }
            }
            // 特殊渠道支付提示信息
            Integer channelId = Optional.ofNullable(orderPayDIO.getChannelId()).orElse(0);
            String msg;
            switch (channelId) {
                case OrderConsts.CHANNEL_ID_DJ58_DAG:
                    msg = "请用微信或支付宝扫码支付";
                    break;
                case OrderConsts.CHANNEL_ID_DAOWEI_ZX:
                case OrderConsts.CHANNEL_ID_KYX:
                case OrderConsts.CHANNEL_ID_DTW:
                    msg = "请用微信或支付宝扫码支付";
                    break;
                case OrderConsts.CHANNEL_ID_TF_INSTALL:
                case OrderConsts.CHANNEL_ID_F8_INSTALL:
                case OrderConsts.CHANNEL_ID_F14_INSTALL:
                    msg = "请用微信或同城APP扫码支付";
                    break;
                default:
                    msg = StringUtil.isBlank(payRepsDRO.getChannelPayTypeMsg()) ? "" : payRepsDRO.getChannelPayTypeMsg();
                    break;
            }
            orderPayDRO.setChannelPayTypeMsg(msg);
            log.info("OrderPayRemoteServiceImpl#payMasterAmount工程师收款支付返回=====>{}", JSON.toJSONString(orderPayDRO));
            return ResponseDTO.success(orderPayDRO);
        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    /**
     * 校验工程师收款支付
     *
     * @param orderId     订单id
     * @param toPayAmount 待支付金额
     * @return
     */
    @Override
    public ResponseDTO<Boolean> verifyPayMasterAmount(Long orderId, Integer toPayAmount) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        if (orderWork == null) {
            return ResponseDTO.fail("工单不存在");
        }
        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return ResponseDTO.fail("工单已取消或已完结");
        }
        if (NumberUtil.isNotNullOrZero(orderWork.getDepositAmount()) && !Objects.equals(orderWork.getDepositStatus(), PayConsts.PAY_STATUS_DONE)) {
            return ResponseDTO.fail("有存在未支付的定金，请先支付定金");
        }
        Integer masterPayStatus = orderWork.getMasterPayStatus();
        if (Objects.equals(PayConsts.PAY_STATUS_DONE, masterPayStatus)) {
            return ResponseDTO.fail("该订单已支付");
        }
        // 待支付金额校验
        if (!Objects.equals(toPayAmount, orderWork.getMasterAmount())) {
            return ResponseDTO.fail("检测到费用信息发生了变化，请联系工程师进行确认");
        }
        if (orderWork.getMasterAmount() == null || orderWork.getMasterAmount() <= 0) {
            return ResponseDTO.fail("检测到费用信息发生了变化，请联系工程师进行确认");
        }
        return ResponseDTO.success(true);
    }

    /**
     * 校验定金支付
     *
     * @param orderId     订单id
     * @param toPayAmount 待支付金额
     * @return
     */
    @Override
    public ResponseDTO<Boolean> verifyPayDepositAmount(Long orderId, Integer toPayAmount) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        if (orderWork == null) {
            return ResponseDTO.fail("工单不存在");
        }
        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return ResponseDTO.fail("工单已取消或已完结");
        }
        Integer depositStatus = orderWork.getDepositStatus();
        if (Objects.equals(PayConsts.PAY_STATUS_DONE, depositStatus)) {
            return ResponseDTO.fail("定金已支付");
        }
        // 待支付金额校验
        if (!Objects.equals(toPayAmount, orderWork.getDepositAmount())) {
            return ResponseDTO.fail("检测到费用信息发生了变化，请联系工程师进行确认");
        }
        if (orderWork.getDepositAmount() == null || orderWork.getDepositAmount() <= 0) {
            return ResponseDTO.fail("检测到费用信息发生了变化，请联系工程师进行确认");
        }
        return ResponseDTO.success(true);
    }

    /**
     * 校验进度款支付
     *
     * @param verifyProgressDIO
     * @return
     */
    @Override
    public ResponseDTO<Boolean> verifyPayProgressAmount(VerifyProgressDIO verifyProgressDIO) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(verifyProgressDIO.getOrderId(), verifyProgressDIO.getOrderId());
        OrderPay orderPay = orderPayService.findOrderPayByKeySrcMaster(verifyProgressDIO.getOrderId(), verifyProgressDIO.getOrderPayId());

        if (orderWork == null) {
            return ResponseDTO.fail("工单不存在");
        }

        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return ResponseDTO.fail("工单已取消或已完结");
        }

        if (Objects.isNull(orderPay)) {
            Integer depositStatus = orderWork.getDepositStatus();
            if (Objects.equals(PayConsts.PAY_STATUS_DONE, depositStatus)) {
                return ResponseDTO.fail("定金已支付");
            }
            // 待支付金额校验
            if (!Objects.equals(verifyProgressDIO.getAmount(), orderWork.getDepositAmount())) {
                return ResponseDTO.fail("检测到费用信息发生了变化，请联系工程师进行确认");
            }
            if (orderWork.getDepositAmount() == null || orderWork.getDepositAmount() <= 0) {
                return ResponseDTO.fail("检测到费用信息发生了变化，请联系工程师进行确认");
            }
            return ResponseDTO.success(true);
        }

        // 待支付金额校验
        if (!Objects.equals(verifyProgressDIO.getAmount(), orderPay.getAmount())) {
            return ResponseDTO.fail("检测到费用信息发生了变化，请联系工程师进行确认");
        }

        if (orderPay.getAmount() == null || orderPay.getAmount() <= 0) {
            return ResponseDTO.fail("检测到费用信息发生了变化，请联系工程师进行确认");
        }

        return ResponseDTO.success(true);
    }

    /**
     * 发送四位短信验证码
     *
     * @param sendAgentPayMessageDIO
     * @return
     */
    @Override
    public ResponseDTO<Boolean> sendAgentPayMessage(SendAgentPayMessageDIO sendAgentPayMessageDIO) {
        log.info("发送代付短信{}", JSON.toJSONString(sendAgentPayMessageDIO));
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(sendAgentPayMessageDIO.getOrderId(), sendAgentPayMessageDIO.getWorkId());
        if (orderWork == null) {
            return ResponseDTO.fail("工单不存在");
        }

        Integer payAmountType;
        if (NumberUtil.isNotNullOrZero(sendAgentPayMessageDIO.getOrderPayId())) {
            payAmountType = OrderConsts.ORDER_ACCEPTANCE_TYPE_PROGRESS;
        } else {
            payAmountType = OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT;
        }
        String orderPayId = NumberUtil.isNullOrZero(sendAgentPayMessageDIO.getOrderPayId()) ? "" : String.valueOf(sendAgentPayMessageDIO.getOrderPayId());

        String url = String.format(orderAgentPayUrl, sendAgentPayMessageDIO.getOrderId(), payAmountType, orderPayId); // 代付url
        ShortLinkDIO shortLinkDIO = new ShortLinkDIO();
        shortLinkDIO.setBussinessId(MessageConsts.APP_MSG_AGENT_PAY);
        shortLinkDIO.setName(sendAgentPayMessageDIO.getOrderId() + "ap:" + DateUtil.toString(DateUtil.getNow()));        // 名字不能重复
        shortLinkDIO.setLink(url);
        shortLinkDIO.setValidEndTime(DateUtil.addDays(DateUtil.getNow(), 7));
        logger.info("订单号【{}】获取代付短链接getShortLink入参【{}】)", sendAgentPayMessageDIO.getOrderId(), shortLinkDIO);
        ResponseDTO<ShortLinkDRO> resp = shortLinkModifyRemoteService.getShortLink(shortLinkDIO);
        logger.info("订单号【{}】获取代付短链接getShortLink出参【{}】)", sendAgentPayMessageDIO.getOrderId(), resp);
        String short_link = "";
        if (!resp.isSuccess()) {
            return ResponseDTO.fail("短链接生成失败");
        }

        short_link = resp.getData().getQrCodeId();

        Map<String, String> smsMap = new HashMap<>();
        smsMap.put("order_id", String.valueOf(sendAgentPayMessageDIO.getOrderId()));
        smsMap.put("short_link", short_link);
        log.info("代付短信参数{}", smsMap);

        SmsMessageDTO smsMessageDTO = SmsMessageDTO.builder()
                .orderId(sendAgentPayMessageDIO.getOrderId())
                .businessId(sendAgentPayMessageDIO.getOrderId())
                .ruleId(MessageConsts.APP_MSG_AGENT_PAY)
                .mobile(sendAgentPayMessageDIO.getPhone())
                .channelId(String.valueOf(orderWork.getChannelId()))
                .cityId(String.valueOf(orderWork.getCityId()))
                .params(JSON.toJSONString(smsMap))
                .build();
        boolean b = messageSendBaseService.sendTextMessage(smsMessageDTO);
        return b ? ResponseDTO.success() : ResponseDTO.fail("消息发送失败");
    }

    @Override
    public ResponseDTO<Boolean> checkWarrantyAmount(Long orderId) {
        List<OrderPay> orderPays = orderPayService.listOrderPayByOrderId(orderId);
        Integer warrantyPaymentAmount = orderPays.stream()
                .filter(x -> Objects.equals(x.getAmountType(), OrderPayConsts.ORDER_PAY_MASTER)
                        && Objects.equals(PayConsts.PAY_TRADE_TYPE_INTIME, x.getTradeType())
                        && Objects.equals(PayConsts.PAY_CHANNEL_PLATFORM_DEPOSIT, x.getPayChannelId()))
                .mapToInt(OrderPay::getAmount).sum();
        return ResponseDTO.success(NumberUtil.isNotNullOrZero(warrantyPaymentAmount));
    }
}
